// ****************************************************************************
// *     Filename:  MySD.cc
// *  Description:  Sensitive Detector
// *      License:  Geant4 Software License 
// *                http://geant4.cern.ch/license/LICENSE.html
// *       Author:  Tran Hoai Nam (nam), nam@kuno-g.phys.sci.osaka-u.ac.jp
// * Organization:  Osaka University
// *      Created:  2012-09-14 13:04:12
// ****************************************************************************
#include "MySD.hh"
#include "MyHit.hh"
//#include "TrackInfo.hh"

#include "G4HCofThisEvent.hh"
#include "G4Step.hh"
#include "G4SDManager.hh"
#include "G4TouchableHistory.hh"
#include "G4Track.hh"
#include "G4VProcess.hh"
#include "G4UnitsTable.hh"
#include "G4ios.hh"

//Constructor: insert detector name into collectionName, set hit code id to -1
MySD::MySD(const G4String & name) : G4VSensitiveDetector(name)
{
	collectionName.insert(name);
	fHCID = -1;
	fEdep = 0.;
}

MySD::~MySD()
{;}

//Initialize the SD: create hit collection; get pointer to the SD from
//SDManager; add the hit collection to hitCollectionOfThisEvent
void MySD::Initialize(G4HCofThisEvent * aHCE) 
{
	fpHC = new MyHitsCollection(SensitiveDetectorName, collectionName[0]);
	if (fHCID<0)
		fHCID = G4SDManager::GetSDMpointer()->GetCollectionID(fpHC);
	aHCE->AddHitsCollection(fHCID,fpHC);
}

//Process hits: read edep, track info
G4bool MySD::ProcessHits(G4Step *aStep, G4TouchableHistory *aHistory) 
{
	G4double edep = aStep->GetTotalEnergyDeposit();
	G4Track *aTrack = aStep->GetTrack();
	G4StepPoint *preStep = aStep->GetPreStepPoint();
	G4StepPoint *postStep = aStep->GetPostStepPoint();
	G4TouchableHandle theTouchable= preStep->GetTouchableHandle();
	G4ThreeVector globalPos = preStep->GetPosition();
	G4int	copyNo = theTouchable->GetCopyNumber();
	G4int stepNo = aStep->GetTrack()->GetCurrentStepNumber();

	if (edep > 0)
	{
		G4double time = (preStep->GetGlobalTime() + postStep->GetGlobalTime())/2;
		MyHit *aCaloHit = new MyHit();
		aCaloHit->SetHitType(MyHit::CaloHit);
		aCaloHit->Setedep(edep);
		aCaloHit->SetCopyNo(copyNo);
		aCaloHit->SetTime(time);
		//aCaloHit->Print();
		//fEdep += edep;
		fpHC->insert(aCaloHit);
	}

	if((aTrack->GetParentID()==0) && (aTrack->GetTrackStatus() == fStopAndKill))
	{
		//G4cout<<"Stopped!Stopped!Stopped!";
		//G4cout<<"Volume: "<<preStep->GetPhysicalVolume()->GetName()<<G4endl;
		G4ThreeVector localPos = 
			theTouchable->GetHistory()->GetTopTransform().TransformPoint(globalPos);
		G4double time = preStep->GetGlobalTime();

		MyHit *aTrackerHit = new MyHit();
		aTrackerHit->SetHitType(MyHit::TrackerHit);
		aTrackerHit->SetPriStopFlag();
		aTrackerHit->SetStopPoint(localPos);
		aTrackerHit->SetStopTime(time);
		aTrackerHit->SetName(aTrack->GetDefinition()->GetParticleName());
		fpHC->insert(aTrackerHit);
		//aTrackerHit->Print();
	}

	if ( preStep->GetStepStatus() == fGeomBoundary )
	{
		//new TrackInfo(aTrack);
		MyHit *aTrackerHit = new MyHit();
		G4ThreeVector localPos = 
			theTouchable->GetHistory()->GetTopTransform().TransformPoint(globalPos);
		G4double time = preStep->GetGlobalTime();

		aTrackerHit->SetHitType(MyHit::TrackerHit);
		aTrackerHit->SetDirection(1);
		aTrackerHit->SetTrackID(aTrack->GetTrackID());
		aTrackerHit->SetPos(localPos);
		aTrackerHit->SetTime(time);
		aTrackerHit->SetPID(aTrack->GetDefinition()->GetPDGEncoding());
		aTrackerHit->SetKE(preStep->GetKineticEnergy());
		aTrackerHit->SetName(aTrack->GetDefinition()->GetParticleName());
		fpHC->insert(aTrackerHit);
	}

	if ( postStep->GetStepStatus() == fGeomBoundary )
	{
		//TrackInfo * aTrkInfo = new TrackInfo(aTrack);
		MyHit *aTrackerHit = new MyHit();
		//Note: the post step point of this step belongs to the next volume; so in
		//order to get local position of the step, the touchable must be get from
		//preStep. The post step point lies on the boundary of the two volume, so
		//the global position is at postStepPoint.
		theTouchable = preStep->GetTouchableHandle();
		globalPos = postStep->GetPosition();
		G4ThreeVector localPos = 
			theTouchable->GetHistory()->GetTopTransform().TransformPoint(globalPos);
		G4double time = postStep->GetGlobalTime();

		aTrackerHit->SetHitType(MyHit::TrackerHit);
		aTrackerHit->SetDirection(-1);
		aTrackerHit->SetTrackID(aTrack->GetTrackID());
		aTrackerHit->SetPos(localPos);
		aTrackerHit->SetTime(time);
		aTrackerHit->SetPID(aTrack->GetDefinition()->GetPDGEncoding());
		aTrackerHit->SetName(aTrack->GetDefinition()->GetParticleName());
		aTrackerHit->SetKE(preStep->GetKineticEnergy());
		fpHC->insert(aTrackerHit);
		//delete aTrkInfo;
	}

	if (stepNo==1) 
	{ 
		G4ThreeVector localPos = 
			theTouchable->GetHistory()->GetTopTransform().TransformPoint(globalPos);
		G4double time = preStep->GetGlobalTime();

		MyHit *aTrackerHit = new MyHit();
		aTrackerHit->SetHitType(MyHit::TrackerHit);
		aTrackerHit->SetNewFlag();
		aTrackerHit->SetNewPoint(localPos);
		aTrackerHit->SetNewTime(time);
		aTrackerHit->SetNewName(aTrack->GetDefinition()->GetParticleName());
		aTrackerHit->SetNewPID(aTrack->GetDefinition()->GetPDGEncoding());
		aTrackerHit->SetNewKE(preStep->GetKineticEnergy());
		aTrackerHit->SetNewTrackID(aTrack->GetTrackID());
		fpHC->insert(aTrackerHit);
	}

	return true;
}

void MySD::EndOfEvent(G4HCofThisEvent *aHCE) 
{
	//G4cout<<"Det: "<<SensitiveDetectorName;
	//G4cout<<", total edep: "<<fEdep<<G4endl;
}
